#include "Application.h"
#include "Game.h"
#include "util/StringBuilder.h"
#include "util/RaiiWrapper.h"
#include "util/Timer.h"

namespace Steak {
	Application::Application() {
		std::clog << "\nApplication initiated\n";
	}

	Application::~Application() {
		std::clog << "Application terminated\n";
	}

	bool Application::run() {
		using namespace util;
		if ( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
			throw std::runtime_error( StringBuilder() << "Unable to initialize SDL: " << SDL_GetError() );
		RaiiWrapper<void(*)()> autoSDL( SDL_Quit );

		if ( !SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL | SDL_DOUBLEBUF ) )
			throw std::runtime_error( StringBuilder() << "Unable to set video mode: " << SDL_GetError() );

		Game g;

		// Timing
		Timer t;
		double bukkit = 0.;
		unsigned updatesPerSecond = 40;
		double secondsPerUpdate = 1.f / updatesPerSecond;
		float secondsPerUpdateF = (float)secondsPerUpdate;

		t.start();
		bool running = true;
		do {
			// Process window events
			SDL_Event ev;
			while ( SDL_PollEvent(&ev) ) {
				switch ( ev.type ) {
					case SDL_KEYDOWN: {
						int key = ev.key.keysym.sym;
						if ( key == SDLK_ESCAPE || key == SDLK_F9 )
							return key == SDLK_F9;
					} break;

					case SDL_QUIT: {
						running = false;
						break;
					}
				}
			}

			// Update timer
			double elapsed = t.poll();
			bukkit += elapsed;
			int updates = (int)std::floor(bukkit / updatesPerSecond);
			bukkit = std::fmod( bukkit, secondsPerUpdate );

			// Update game
			while ( updates-- > 0 )
				running &= g.update( secondsPerUpdateF );			

			// Render game
			glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
			g.render( float(bukkit / secondsPerUpdate) );
			SDL_GL_SwapBuffers();
		} while ( running );
		t.stop();

		return false;
	}
}